package com.content.scaffold.common.mybatis.query;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.content.scaffold.common.annotation.TableAlias;
import lombok.Getter;
import org.springframework.core.annotation.AnnotationUtils;

import java.io.Serial;
import java.util.*;
import java.util.function.Consumer;

/**
 * 增强型查询构造器
 *
 * @author xiaojl
 * @param <T> 实体类型
 */
public class CriteriaQuery<T> extends QueryWrapper<T> {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 表别名映射 (实体名 -> 别名)
     */
    private final Map<String, String> aliasMap = new HashMap<>();

    /**
     * 自定义查询字段
     */
    private final List<String> selectFields = new ArrayList<>();

    /**
     * 分页参数
     * -- GETTER --
     *  获取分页参数

     */
    @Getter
    private PageQueryParams<T> pageQueryParams;

    /**
     * 是否已初始化
     */
    private boolean initialized = false;

    public CriteriaQuery() {
        super();
    }

    public CriteriaQuery(PageQuery pageQuery) {
        this(new PageQueryParams<>(pageQuery));
    }

    public CriteriaQuery(PageQueryParams<T> pageQueryParams) {
        super();
        this.pageQueryParams = pageQueryParams;
        initSorting();
    }

    /**
     * 初始化排序条件
     */
    private void initSorting() {
        if (initialized || pageQueryParams == null) {
            return;
        }

        String sort = pageQueryParams.getQuery().getSort();
        if (StringUtils.isNotBlank(sort)) {
            String order = Optional.ofNullable(pageQueryParams.getQuery().getOrder())
                    .orElse(SqlKeyword.DESC.getSqlSegment());

            Arrays.stream(sort.split(","))
                    .map(StringUtils::camelToUnderline)
                    .forEach(field -> {
                        if (SqlKeyword.ASC.getSqlSegment().equalsIgnoreCase(order)) {
                            this.orderByAsc(field);
                        } else {
                            this.orderByDesc(field);
                        }
                    });
        }
        initialized = true;
    }

    /**
     * 创建表别名关联
     */
    public CriteriaQuery<T> alias(String entity, String alias) {
        if (StringUtils.isNotBlank(entity) && StringUtils.isNotBlank(alias)) {
            this.aliasMap.put(entity, alias);
        }
        return this;
    }

    /**
     * 通过实体类注解创建表别名
     */
    public CriteriaQuery<T> alias(Class<?> clazz) {
        TableAlias tableAlias = AnnotationUtils.findAnnotation(clazz, TableAlias.class);
        if (tableAlias != null && StringUtils.isNotBlank(tableAlias.value())) {
            this.aliasMap.put(tableAlias.value(), tableAlias.value());
        }
        return this;
    }

    /**
     * 添加查询字段
     */
    public CriteriaQuery<T> selectField(String field) {
        if (StringUtils.isNotBlank(field)) {
            this.selectFields.add(field);
        }
        return this;
    }

    /**
     * 添加多个查询字段
     */
    public CriteriaQuery<T> selectFields(String... fields) {
        if (fields != null && fields.length > 0) {
            Arrays.stream(fields)
                    .filter(StringUtils::isNotBlank)
                    .forEach(this.selectFields::add);
        }
        return this;
    }

    /**
     * 构建最终查询SQL
     */
    @Override
    public String getSqlSelect() {
        if (CollectionUtils.isNotEmpty(selectFields)) {
            return String.join(", ", selectFields);
        }
        return super.getSqlSelect();
    }

    /**
     * 等于条件 (自动过滤null和特定无效值)
     */
    @Override
    public CriteriaQuery<T> eq(String column, Object val) {
        if (isValidValue(val)) {
            super.eq(column, val);
        }
        return this;
    }

    /**
     * LIKE条件
     */
    @Override
    public CriteriaQuery<T> like(String column, Object val) {
        if (isValidValue(val)) {
            super.like(column, val);
        }
        return this;
    }

    /**
     * IN条件
     */
    @Override
    public CriteriaQuery<T> in(String column, Collection<?> values) {
        if (CollectionUtils.isNotEmpty(values)) {
            super.in(column, values);
        }
        return this;
    }

    /**
     * BETWEEN条件
     */
    @Override
    public CriteriaQuery<T> between(String column, Object val1, Object val2) {
        if (isValidValue(val1) && isValidValue(val2)) {
            super.between(column, val1, val2);
        }
        return this;
    }

    /**
     * 大于等于条件
     */
    @Override
    public CriteriaQuery<T> ge(String column, Object val) {
        if (isValidValue(val)) {
            super.ge(column, val);
        }
        return this;
    }

    /**
     * 小于等于条件
     */
    @Override
    public CriteriaQuery<T> le(String column, Object val) {
        if (isValidValue(val)) {
            super.le(column, val);
        }
        return this;
    }

    /**
     * 嵌套条件
     */
    @Override
    public CriteriaQuery<T> nested(Consumer<QueryWrapper<T>> consumer) {
        if (consumer != null) {
            consumer.accept(this);
        }
        return this;
    }

    /**
     * 动态条件判断
     */
    public CriteriaQuery<T> condition(boolean condition, Consumer<CriteriaQuery<T>> consumer) {
        if (condition && consumer != null) {
            consumer.accept(this);
        }
        return this;
    }

    /**
     * 获取表别名映射
     */
    public Map<String, String> getAliasMap() {
        return Collections.unmodifiableMap(aliasMap);
    }

    /**
     * 检查值是否有效
     */
    private boolean isValidValue(Object val) {
        if (val == null) {
            return false;
        }

        // 过滤特定无效值
        if (val instanceof Number) {
            return ((Number) val).longValue() != -1L;
        }

        if (val instanceof String) {
            return !((String) val).trim().isEmpty();
        }

        if (val instanceof Collection) {
            return !((Collection<?>) val).isEmpty();
        }

        return true;
    }

    // 更多条件方法可以按需添加...

    /**
     * 日期范围条件
     */
    public CriteriaQuery<T> dateBetween(String column, Date start, Date end) {
        if (start != null && end != null) {
            super.between(column, start, end);
        } else if (start != null) {
            super.ge(column, start);
        } else if (end != null) {
            super.le(column, end);
        }
        return this;
    }

    /**
     * 字符串不为空条件
     */
    public CriteriaQuery<T> isNotBlank(String column, String val) {
        if (StringUtils.isNotBlank(val)) {
            super.eq(column, val);
        }
        return this;
    }

    /**
     * 构建排序条件
     */
    public CriteriaQuery<T> orderBy(String column, boolean isAsc) {
        if (StringUtils.isNotBlank(column)) {
            if (isAsc) {
                super.orderByAsc(column);
            } else {
                super.orderByDesc(column);
            }
        }
        return this;
    }
}